package com.czt.mail.controller;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import com.aliyuncs.exceptions.ClientException;
import com.czt.mail.entity.OssTokenVO;
import com.czt.mail.limit.CounterLimiter;
import com.czt.mail.service.OssService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("file")
@Slf4j
public class ApiFileController {

    @Autowired
    private ThreadPoolTaskExecutor ioThreadPoolTaskExecutor;

    @Autowired
    private OssService ossService;

    @Autowired
    private CounterLimiter counterLimiter;

    @GetMapping("/test")
    public String test() {
        if (counterLimiter.limit()) {
            return "请求频繁";
        }
        return "ok";
    }

    @GetMapping("/getToken")
    public OssTokenVO getToken() throws ClientException {
        return ossService.getToken();
    }


    private static final String ENDPOINT = "https://oss-cn-beijing.aliyuncs.com";
    private static final String ACCESS_KEY_ID = "LTAI5tPSuPeH3HqHpDBGnmCx";
    private static final String ACCESS_KEY_SECRET = "bOOcGCHeyhRLg0zRWBuqmJrgW2ORli";
    private static final String BUCKET_NAME = "test-clear-ex-web";


    @PostMapping("/upload")
    public String uploadFile(MultipartFile file) throws IOException {
//        // 创建OSSClient实例。
//        OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
//
//        long startTime = System.currentTimeMillis(); // 开始时间
//        try {
//            // 初始化分片上传。
//            String key = file.getOriginalFilename();
//            InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(BUCKET_NAME, key);
//            String uploadId = ossClient.initiateMultipartUpload(request).getUploadId();
//
//            // 分片上传。
//            final int partSize = 5 * 1024 * 1024; // 5MB
//            int fileSize = (int) file.getSize();
//            int partCount = (fileSize + partSize - 1) / partSize;
//
//            List<Future<PartETag>> futures = new ArrayList<>();
//
//            for (int i = 0; i < partCount; i++) {
//                int partNumber = i + 1;
//                int startPos = i * partSize;
//                int curPartSize = (i + 1 == partCount) ? (fileSize - startPos) : partSize;
//
//                InputStream inputStream = file.getInputStream();
//                inputStream.skip(startPos);
//
//                Callable<PartETag> task = () -> {
//                    UploadPartRequest uploadPartRequest = new UploadPartRequest();
//                    uploadPartRequest.setBucketName(BUCKET_NAME);
//                    uploadPartRequest.setKey(key);
//                    uploadPartRequest.setUploadId(uploadId);
//                    uploadPartRequest.setInputStream(inputStream);
//                    uploadPartRequest.setPartSize(curPartSize);
//                    uploadPartRequest.setPartNumber(partNumber);
//
//                    UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
//                    inputStream.close();
//                    return uploadPartResult.getPartETag();
//                };
//
//                futures.add((ioThreadPoolTaskExecutor).submit(task));
//            }
//
//            List<PartETag> partETags = new ArrayList<>();
//            for (Future<PartETag> future : futures) {
//                try {
//                    partETags.add(future.get());
//                } catch (InterruptedException | ExecutionException e) {
//                    e.printStackTrace();
//                }
//            }
//
//            // 完成分片上传。
//            CompleteMultipartUploadRequest completeMultipartUploadRequest =
//                    new CompleteMultipartUploadRequest(BUCKET_NAME, key, uploadId, partETags);
//            ossClient.completeMultipartUpload(completeMultipartUploadRequest);
//
//            long endTime = System.currentTimeMillis(); // 结束时间
//            long duration = endTime - startTime; // 计算耗时
//
//            String formattedDuration = formatDuration(duration);
//
//            // 构建文件URL
//            String url = ENDPOINT.split("//")[0] + "//" + BUCKET_NAME + "." + ENDPOINT.split("//")[1] + "/" + key;
//
//            log.info("文件路径为:{}，上传所用时间:{}",url,formattedDuration);
//            return url;
//        } catch (Exception e) {
//            e.printStackTrace();
//            return "上传文件失败";
//        } finally {
//            // 关闭OSSClient。
//            ossClient.shutdown();
//        }
            // 创建OSSClient实例。
            OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);

            long startTime = System.currentTimeMillis(); // 开始时间
            try {
                // 初始化分片上传。
                String key = file.getOriginalFilename();
                InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(BUCKET_NAME, key);
                String uploadId = ossClient.initiateMultipartUpload(request).getUploadId();

                // 分片上传。
                final int partSize = 5 * 1024 * 1024; // 5MB
                int fileSize = (int) file.getSize();
                int partCount = (fileSize + partSize - 1) / partSize;

                List<PartETag> partETags = new ArrayList<>();

                for (int i = 0; i < partCount; i++) {
                    int startPos = i * partSize;
                    int curPartSize = (i + 1 == partCount) ? (fileSize - startPos) : partSize;

                    InputStream inputStream = file.getInputStream();
                    inputStream.skip(startPos);

                    UploadPartRequest uploadPartRequest = new UploadPartRequest();
                    uploadPartRequest.setBucketName(BUCKET_NAME);
                    uploadPartRequest.setKey(key);
                    uploadPartRequest.setUploadId(uploadId);
                    uploadPartRequest.setInputStream(inputStream);
                    uploadPartRequest.setPartSize(curPartSize);
                    uploadPartRequest.setPartNumber(i + 1);

                    UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
                    partETags.add(uploadPartResult.getPartETag());
                    inputStream.close();
                }

                // 完成分片上传。
                CompleteMultipartUploadRequest completeMultipartUploadRequest =
                        new CompleteMultipartUploadRequest(BUCKET_NAME, key, uploadId, partETags);
                ossClient.completeMultipartUpload(completeMultipartUploadRequest);

                long endTime = System.currentTimeMillis(); // 结束时间
                long duration = endTime - startTime; // 计算耗时

                String formattedDuration = formatDuration(duration);

                // 构建文件URL
                String url = ENDPOINT.split("//")[0] + "//" + BUCKET_NAME + "." + ENDPOINT.split("//")[1] + "/" + key;

                log.info("文件路径为:{}，上传所用时间:{}",url,formattedDuration);
                return url;
            } catch (Exception e) {
                e.printStackTrace();
                return "上传文件失败";
            } finally {
                // 关闭OSSClient。
                ossClient.shutdown();
            }

    }

    private String formatDuration(long millis) {
        long hours = TimeUnit.MILLISECONDS.toHours(millis);
        long minutes = TimeUnit.MILLISECONDS.toMinutes(millis) % 60;
        long seconds = TimeUnit.MILLISECONDS.toSeconds(millis) % 60;

        return String.format("%02d:%02d:%02d", hours, minutes, seconds);
    }
}
